package cn.javass.framework.ioc.config;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

import cn.javass.framework.aop.annotation.IInterceptor;
import cn.javass.framework.ioc.annotation.IInject;
import cn.javass.framework.ioc.annotation.IService;
import cn.javass.framework.ioc.core.BeanDefinition;
import cn.javass.framework.ioc.core.Container;



public class IOCConfiguration {
	private static IOCConfiguration cfg = null;
	
	public static IOCConfiguration configure(){
		if(cfg==null){
			synchronized (IOCConfiguration.class) {
				cfg = new IOCConfiguration();
				cfg.builder();
			}
		}
		return cfg;
	}
	
	private void builder(){
		String rootStr = getClass().getClassLoader().getResource(".").getPath().substring(1);
		File root = new File(rootStr);
		parse(root,rootStr.length());
	}
	
	private void parse(File root,int length){
		if(root.isDirectory()){
			for(File file:root.listFiles()){
				parse(file,length);
			}
		}else{
			
			if(root.getName().endsWith(".class")){
				
				String clazzName = root.getAbsolutePath();
				clazzName = clazzName.substring(length,clazzName.length()-6).replace(File.separatorChar, '.');
				
				processAnnotation(clazzName);
			}
		}
	}
	
	private void processAnnotation(String clazzName){
		try{
			
			Class clazz = Class.forName(clazzName);
			if(clazz.isAnnotationPresent(IService.class)){
				makeBeanDefination(clazz);
				System.out.println(clazz.getName());
			}
		}catch (Throwable e) {
		}
	}
	
	private void makeBeanDefination(Class clazz) throws Exception{
		BeanDefinition bd = new BeanDefinition();
		IService serviceAnnotation = (IService)clazz.getAnnotation(IService.class);
		bd.setBeanClassName(clazz.getName());
		bd.setId(serviceAnnotation.id());
		bd.setScope(serviceAnnotation.scope());
		for(Field field:clazz.getDeclaredFields()){
			if(field.isAnnotationPresent(IInject.class)){
				IInject service = field.getAnnotation(IInject.class);
				bd.getProperties().put(field.getName(), service.id());
			}
		}
		makeBeanInterceptors(clazz,bd);
		Container.getBeanDefinitions().put(bd.getId(),bd);
	}
	
	private void makeBeanInterceptors(Class clazz,BeanDefinition bd){
		if(clazz.isAnnotationPresent(IInterceptor.class)){
			IInterceptor iInterceptor = (IInterceptor) clazz.getAnnotation(IInterceptor.class);
			Class[] classInterceptors = iInterceptor.classes();
			putInterceptors(classInterceptors);
			bd.setClassInterceptors(Arrays.asList(classInterceptors));
		}
		for(Method method:clazz.getMethods()){
			if(method.isAnnotationPresent(IInterceptor.class)){
				IInterceptor iInterceptor = method.getAnnotation(IInterceptor.class);
				Class[] methodIntecerptors = iInterceptor.classes(); 
				putInterceptors(methodIntecerptors);
				bd.getMethodInterceptors().put(method.getName(),Arrays.asList(methodIntecerptors));
			}
		}
		
	}
	
	private void putInterceptors(Class[] interceptors){
		for(Class e:interceptors){
			Container.putInterceptor(e,null);
		}
	}

	public static void main(String[] args) {
		IOCConfiguration.configure();
		System.out.println(Container.getBeanDefinitions().size());
	}
}
